﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using FreightSoft.Models;

namespace FreightSoft.Controllers
{
    public class ShipmentController : Controller
    {

        private Entities db = new Entities();
        //
        // GET: /Shipment/
        
        public ActionResult Index(int? id)
        {
            if (id != null)
            {
                db.SHIPMENTs.Find(id);
                return View(db.SHIPMENTs.Find(id));
            }
            else
            {
                return View(db.SHIPMENTs.ToList());
            }
        }

        public ActionResult AddShipments(int schedule_id)
        {
            ViewBag.SCHEDULE_ID = schedule_id;
            var model = TempData["list"] as List<SHIPMENT>;
            return View(model.ToList());

        }



        public ActionResult AddOrders(decimal shipment_id)
        {
            SHIPMENT record = db.SHIPMENTs.Find(shipment_id);

            List<CUSTOMER_ORDER> order_list = GetOrderForShipment(shipment_id, record.ORIGINPORT, record.DESTINATIONPORT);
            //return View(shipments.ToList());
            ViewBag.SHIPMENT_ID = shipment_id;
            TempData["Order_list"] = order_list.ToList();
            return RedirectToAction("AddOrders", "ShipmentLine", new { shipment_id = shipment_id });
            //return View();
        }


        // get order records to attach to a particular shipment
        protected List<CUSTOMER_ORDER> GetOrderForShipment(decimal shipment_id, string origin_port, string dest_port)
        {
            SHIPMENT shipment = db.SHIPMENTs.Find(shipment_id);
            var orders_list = from orders in db.CUSTOMER_ORDER
                            where (orders.SOURCE == origin_port) && (orders.DESTINATION == dest_port)
                            && (orders.STATUS == "Invoiced")
                            && (shipment.PLANNED_DELIVERY_DATE <= orders.WANTED_DELIVERY_DATE)
                            select orders;
            return orders_list.ToList();
        }
        // add shipment to a schedule
        public ActionResult Add(decimal shipment_id, decimal schedule_id)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    //ShipmentScheduleController controller = new ShipmentScheduleController();
                    SHIPMENTSCHEDULE sch = db.SHIPMENTSCHEDULEs.Find(schedule_id);
                    SHIPMENT shipment = db.SHIPMENTs.Find(shipment_id);

                    if (( sch.SHIP.TOTALVOLUME >= (GetTotalVolumeOfSchedule(schedule_id) + shipment.VOLUME)) && (sch.SHIP.TOTALWEIGHT >= (GetTotalWeightOfSchedule(schedule_id) + shipment.WEIGHT)))
                    {
                        shipment.SCHEDULEID = schedule_id;
                        shipment.STATUS = "OnBoard";
                        //db.SHIPMENTs.Add(shipment);
                        db.SaveChanges();

                        ViewBag.SCHEDULE_ID = schedule_id;
                        //SHIPMENTSCHEDULE sch = db.SHIPMENTSCHEDULEs.Find(schedule_id);
                        List<SHIPMENT> list = GetShipmentsForTransport(sch.ROUTEID);
                        return View("AddShipments", list.ToList());
                    }
                    else
                    {
                        TempData["error"] = "Not enough space in the Ship to add shipment " + shipment_id.ToString();
                        return RedirectToAction("Details", "ShipmentSchedule", new { id = sch.SCHEDULEID });
                    }
                    
                }
                return View("Index");
            }
            catch (System.Data.DataException)
            {
                ModelState.AddModelError("", "");
            }
            return View("Index");

        }

        // remove shipment from schedule
        public ActionResult Remove(decimal shipment_id)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    SHIPMENT shipment = db.SHIPMENTs.Find(shipment_id);
                    decimal schedule_id = Convert.ToDecimal(shipment.SCHEDULEID);
                    //decimal schedule_id = shipment.SCHEDULEID ?? 0;
                        shipment.SCHEDULEID = null;
                        shipment.STATUS = "Released";
                        db.SaveChanges();

                        ViewBag.SCHEDULE_ID = schedule_id;

                        return RedirectToAction("Details", "ShipmentSchedule", new { id = schedule_id });


                }
                return View("Index");
            }
            catch (System.Data.DataException)
            {
                ModelState.AddModelError("", "");
            }
            return View("Index");

        }



        // ------------
        public decimal GetTotalVolumeOfSchedule(decimal schedule_id)
        {
            SHIPMENTSCHEDULE schedule = db.SHIPMENTSCHEDULEs.Find(schedule_id);
            var records = from shipments in db.SHIPMENTs
                          where ((shipments.STATUS == "OnBoard") || (shipments.STATUS == "InTransit"))
                          && (shipments.SCHEDULEID == schedule_id)
                          select shipments;
            //decimal tot_weight = 0;
            decimal tot_volume = 0;
            foreach (var i in records)
            {
                // tot_weight += i.WEIGHT;
                tot_volume += i.VOLUME ?? 0;
            }
            return tot_volume;
        }

        public decimal GetTotalWeightOfSchedule(decimal schedule_id)
        {
            SHIPMENTSCHEDULE schedule = db.SHIPMENTSCHEDULEs.Find(schedule_id);

            // IQueryable<SHIPMENT> shipments = db.SHIPMENTs.Where(p => p.SCHEDULEID == schedule_id);
            // consider only the shipments that are in the ship
            var records = from shipments in db.SHIPMENTs
                          where ((shipments.STATUS == "OnBoard") || (shipments.STATUS == "InTransit"))
                          && (shipments.SCHEDULEID == schedule_id)
                          select shipments;


            decimal tot_weight = 0;
            //decimal tot_volume = 0;
            foreach (var i in records)
            {
                if (i.WEIGHT != null)
                    tot_weight += i.WEIGHT ?? 0;
                //tot_volume += i.VOLUME;
            }
            return tot_weight;
        }
        // ------------
        //public decimal GetShipmentT
        protected List<SHIPMENT> GetShipmentsForTransport(string route_id)
        {
            var port_list = from route in db.ROUTEs
                            where (route.ROUTE_ID == route_id)
                            select route.PORT_ID;
            //select route;
            var my = port_list.ToList();
            var my1 = port_list.ToList();
            var records = from shipments in db.SHIPMENTs
                          where (port_list.Contains(shipments.ORIGINPORT)) && (port_list.Contains(shipments.DESTINATIONPORT))
                          && (shipments.STATUS == "Released") && (shipments.SCHEDULEID == null)
                          select shipments;
            var tt = records.ToList();
            var yy = records.ToList();
            //list<shipment> records = new list<shipment>();
            return records.ToList();
        }
        public ActionResult ViewAllShipments()
        {
            var shipments = db.SHIPMENTs.ToList();
            return View(shipments);
        }

        public ActionResult ViewShipments(decimal? schedule_id)
        {
            var shipments = db.SHIPMENTs.Where(s => s.SCHEDULEID == schedule_id).ToList();
            return View(shipments);
        }

        public void AddShipmentLines(decimal? schedule_id, string route_id, string org_port_id, string dest_port_id)
        {
            var shipments = db.SHIPMENTs.Where(s => s.SCHEDULEID == schedule_id).ToList();
        }

        

        public ActionResult Create()
        {
            //ViewBag.ORIGINPORT = new SelectList(db.PORTs, "ORIGINPORT", "Port_Name");
            //ViewBag.DESTINATIONPORT = new SelectList(db.PORTs, "DESTINATIONPORT", "Port_Name");

            var port_list = db.PORTs.ToList();
            foreach (var i in port_list)
            {
                i.PORT_ID = i.PORT_ID.Trim();
            }
            var PortList = port_list;
            var dropdownList = new SelectList(PortList, "Port_Id", "Port_Name");
            ViewData["Org_Port_ID"] = dropdownList;
            ViewData["Dest_Port_ID"] = dropdownList;
            return View();
        }

        //
        // POST: /Shipment/Create
        [HttpPost]
        public ActionResult Create(SHIPMENT shipment, FormCollection collection)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    //TrackingController track = new TrackingController();
                    // call create new method here
                    shipment.ORIGINPORT = collection.Get("selectedOriginPortId");
                    shipment.DESTINATIONPORT = collection.Get("selectedDestPortId");
                    //var idd = db.SHIPMENTs.Count();
                    //var my1 = idd + 1001;

                    // shipment.SHIPMENTID = my1;
                    shipment.STATUS = "Planned";

                    int hours = 0;
                    double days = 0;
                    if (shipment.PLANNED_START_DATE.HasValue)
                    {
                        hours = calculateTime(shipment.ORIGINPORT, shipment.DESTINATIONPORT);
                        days = hours / 24;
                        DateTime planned = shipment.PLANNED_START_DATE ?? DateTime.Now;
                        planned = planned.AddDays(days);
                        shipment.PLANNED_DELIVERY_DATE = planned;
                    }
                    
                    if (!shipment.VOLUME.HasValue)
                    {
                        shipment.VOLUME = 0;
                    }
                    if (!shipment.WEIGHT.HasValue)
                    {
                        shipment.WEIGHT = 0;
                    }
                    shipment.SHIPMENTID = db.SHIPMENTs.Max(s => s.SHIPMENTID) + 1;
                    db.SHIPMENTs.Add(shipment);
                    db.SaveChanges();

                    db.Entry(shipment).Reload();
                    var ii = db.SHIPMENTs.Max(p => p.SHIPMENTID);

                    return RedirectToAction("Details", new { Id = ii });
                    // return RedirectToAction("Index");
                }
            }
            catch (System.Data.DataException ex)
            {
                ModelState.AddModelError("", "");
            }
            return View(shipment);
        }

        public int calculateTime(string originPort, string destPort)
        {
            var routecoordinate_ = (from r in db.ROUTECOORDINATES where r.ORIGIN_PORT_ID == originPort && r.COORDINATE_ORDER == 0 select r).ToList().First();
            int time_ = (int)routecoordinate_.DURATION.GetValueOrDefault();
            if (routecoordinate_.DEST_PORT_ID != destPort)
            {
                time_ += calculateTime(routecoordinate_.DEST_PORT_ID, destPort);
            }
            return time_;
        }

        //
        // GET: /ShipmentSchedule/Details/5

        public ActionResult Details(decimal id)
        {
            SHIPMENT shipment = db.SHIPMENTs.Find(id);
            PORT Org_port = db.PORTs.Find(shipment.ORIGINPORT);
            PORT dest_port = db.PORTs.Find(shipment.DESTINATIONPORT);


            shipment.ORIGINPORT = Org_port.PORT_NAME.ToString();
            shipment.DESTINATIONPORT = dest_port.PORT_NAME.ToString();

            if (shipment == null)
            {
                return HttpNotFound();
            }
            
            return View(shipment);
        }

        public ActionResult ShipmentDelNote(decimal id)
        {
            SHIPMENT shipment = db.SHIPMENTs.Find(id);
            PORT Org_port = db.PORTs.Find(shipment.ORIGINPORT);
            PORT dest_port = db.PORTs.Find(shipment.DESTINATIONPORT);

            shipment.ORIGINPORT = Org_port.PORT_NAME.ToString();
            shipment.DESTINATIONPORT = dest_port.PORT_NAME.ToString();

            if (shipment == null)
            {
                return HttpNotFound();
            }
            //return new RazorPDF.PdfResult(shipment, "ShipmentDelNote");
            return View(shipment);
        }

        public ActionResult CreateSchedule()
        {
            return View();
        }
        // *******
        
       
        // *********STATE CHANGES**********

        

        

        public ActionResult Plan(int id)
        {
            SHIPMENT shipment = db.SHIPMENTs.Find(id);
            shipment.STATUS = "Planned";
            db.SaveChanges();
            return RedirectToAction("Details", new { id = id });
        }


        public ActionResult Release(int id)
        {
            SHIPMENT shipment = db.SHIPMENTs.Find(id);
            shipment.STATUS = "Released";
            db.SaveChanges();

            foreach (var i in shipment.SHIPMENTLINEs)
            {
                i.STATUS = "Released";
                db.SaveChanges();
            }
            return RedirectToAction("Details", new { id = id });
        }


        public ActionResult Cancel(int id)
        {
            SHIPMENT shipment = db.SHIPMENTs.Find(id);
            shipment.STATUS = "Cancelled";
            db.SaveChanges();

            foreach (var i in shipment.SHIPMENTLINEs)
            {
                i.STATUS = "Cancelled";
                db.SaveChanges();
            }

            return RedirectToAction("Details", new { id = id });
        }


        public ActionResult Authorize(int id)
        {
            SHIPMENT shipment = db.SHIPMENTs.Find(id);
            shipment.STATUS = "Authorized";
            db.SaveChanges();
            return RedirectToAction("Details", new { id = id });
        }

        public ActionResult Deliver(int id)
        {
            SHIPMENT shipment = db.SHIPMENTs.Find(id);
            shipment.STATUS = "Delivered";
            db.SaveChanges();
            // reduce the weight and volume from the schedule to show the goods are unloaded

            foreach (var i in shipment.SHIPMENTLINEs)
            {
                i.STATUS = "Delivered";
                db.SaveChanges();
                OrdersDelivered((int)i.ORDERID);
            }
            return RedirectToAction("Details", new { id = id });
        }        

        public void OrdersDelivered(int id)
        {
            CUSTOMER_ORDER order = db.CUSTOMER_ORDER.Find(id);
            order.STATUS = "Delivered";
            db.SaveChanges();
        }

        

    }
}
